import json
import requests
import time
import hashlib
import hmac
import sys

from coin.exchange.base.kr_rest.auth_base import AuthKey
from coin2.api_client.common import (SyncQueryer)
from enum import Enum

class TimeInForce(Enum):
  GOOD_TIL_CANCELLED = "GOOD_TIL_CANCELLED"
  IMMEDIATE_OR_CANCEL = "IMMEDIATE_OR_CANCEL"
  FILL_OR_KILL = "FILL_OR_KILL"
  POST_ONLY_GOOD_TIL_CANCELLED = "POST_ONLY_GOOD_TIL_CANCELLED"
  BUY_NOW = "BUY_NOW"
  INSTANT = "INSTANT"

class Direction(Enum):
  SELL = "SELL"
  BUY = "BUY"

class Type(Enum):
  MARKET = "MARKET"
  LIMIT = "LIMIT"
  CEILING_LIMIT = "CEILING_LIMIT"
  CEILING_MARKET = "CEILING_MARKET"

class BittrexAuth(requests.auth.AuthBase):
  def __init__(self, key):
    self._key = AuthKey.from_file(key)

  def _gen_signature(self, timestamp, uri, method, content_hash):
    str_to_sign = f"{timestamp}{uri}{method}{content_hash}"

    sign = hmac.new(self._key.secret_key_bytes, str_to_sign.encode(), digestmod=hashlib.sha512).hexdigest()

    return sign

  def __call__(self, req: requests.PreparedRequest):
    body = ""

    if req.body is not None:
      body = req.body

    if isinstance(body, str):
      body = body.encode()

    timestamp = str(int(time.time() * 1000))
    content_hash = hashlib.sha512(body).hexdigest()
    signature = self._gen_signature(timestamp, req.url, req.method, content_hash)

    req.headers.update({"Api-Key": self._key.access_key})
    req.headers.update({"Api-Timestamp": timestamp})
    req.headers.update({"Api-Content-Hash": content_hash})
    req.headers.update({"Api-Signature": signature})
    req.headers.update({"Content-Type": "application/json"})
    req.prepare_headers(req.headers)

    # print(req.headers)
    # print(req.body)
    # print(req.url)

    return req

class BittrexPrivateClient():
  def __init__(self, key_path: str, ip=None):
    self._auth = BittrexAuth(key_path)
    self._url = "https://api.bittrex.com"

    self._query = SyncQueryer(api_host=self._url, auth=self._auth, ip=ip)

  def get_balance(self):
    method = "GET"
    path = "/v3/balances"

    response = self._query.query(method=method, path=path)
    return response.json()

  def get_open_orders(self):
    method = "GET"
    path = "/v3/orders/open"

    response = self._query.query(method=method, path=path)
    return response.json()

  def history_order(self, page_size: int):
    method = "GET"
    path = "/v3/orders/closed"

    params = {
      "pageSize": page_size,
    }
  
    response = self._query.query(method=method, path=path, params=params)
    return response.json()

  def submit_order(
      self,
      market_symbol: str,
      direction: Direction,
      type: Type,
      time_in_force: TimeInForce,
      quantity: str = None,
      limit: str = None,
      client_order_id: str = None,
    ):
    method = "POST"
    path = "/v3/orders"

    json = {
      "marketSymbol": market_symbol,
      "direction": direction.value,
      "type": type.value,
      "timeInForce": time_in_force.value,
      "quantity": quantity,
      "limit": limit,
      "clientOrderId": client_order_id,
    }
  
    response = self._query.query(method=method, path=path, json=json)
    return response.json()

  def cancel_order(self, order_id: str):
    method = "DELETE"
    path = f"/v3/orders/{order_id}"
  
    response = self._query.query(method=method, path=path)
    return response.json()

# api doc url
# https://bittrex.github.io/api/v3

if __name__ == "__main__":
  key_path = sys.argv[1]

  bittrex = BittrexPrivateClient(key_path)
  # info = bittrex.get_balance()
  info = bittrex.get_open_orders()
  # info = bittrex.cancel_order("8914b15e-7a03-48ab-9e81-ff3a05791b46")
  # info = bittrex.submit_order("BTC-USDT", Direction.BUY, Type.LIMIT, TimeInForce.GOOD_TIL_CANCELLED, "0.00015371", "1000", "00000000-0000-0000-0000-123456789012")
  print(json.dumps(info, indent=2))
